package com.ek.kademlia.task;

import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ek.common.Bucket;
import com.ek.common.FutureResponse;
import com.ek.common.MessageSender;
import com.ek.kademlia.protocol.impl.DefaultStoreRequest;
import com.ek.kademlia.protocol.impl.DefaultStoreResponse;

public class StoreValue extends FutureTask<Void> {
    private static final transient Logger log = LoggerFactory.getLogger(StoreValue.class);

    public StoreValue(final String key, final Serializable value, final List<Bucket> buckets, final byte[] nodeID, final MessageSender sender) {
        super(new Callable<Void>() {

            public Void call() throws Exception {
                List<FutureResponse<DefaultStoreResponse>> responses = new LinkedList<FutureResponse<DefaultStoreResponse>>();
                DefaultStoreRequest request = new DefaultStoreRequest();
                request.setNodeID(nodeID);
                request.setMessageID(UUID.randomUUID().toString().getBytes());
                request.setKey(key);
                request.setValue(value);
                for (Bucket bucket : buckets) {
                    log.debug("send STORE rpc to this bucket:" + bucket);
                    FutureResponse<DefaultStoreResponse> response = sender.sendMessage(request, new InetSocketAddress(bucket.getAddress(), bucket.getPort()));
                    responses.add(response);
                }
                for (FutureResponse<DefaultStoreResponse> futureResponse : responses) {
                    DefaultStoreResponse response = futureResponse.get(2, TimeUnit.SECONDS);
                    if (response != null) {
                        log.debug("received STORE rpc response from this address:" + response.getSocketAddress());
                    }
                }
                return null;
            }
        });
    }
}
